import Vue from 'vue'
import config from '../../../../config/config.js'
import {isEmpty} from '../unit/util.js'

// components
import checkbox from '../table-column/checkbox/index.vue'
import tag from '../../../data/tag/index.vue'

import LayoutObserver from './../unit/layout-observer.js'

import AtyDropDown from '../../../navigation/dropdown/index.vue'
import AtyDropDownPanel from '../../../navigation/dropdown/dropdown-panel/index.vue'
/**
 *
 * @param columns {array}
 * @returns {Array}
 * @description  static function  获取所有栏目数
 */
const getAllColumns = (columns) => {
  const result = []
  columns.forEach((column) => {
    if (column.children) {
      result.push(column)
      result.push.apply(result, getAllColumns(column.children))
    } else {
      result.push(column)
    }
  })
  return result
}

/**
 *
 * @param originColumns
 * @returns {Array}
 * @description  static function  推算行数
 */
const convertToRows = (originColumns, fixed) => {
  let maxLevel = 1
  /**
   *
   * @param column
   * @param parent
   */
  const traverse = (column, parent) => {
    if (parent) {
      column.level = parent.level + 1
      if (maxLevel < column.level) {
        maxLevel = column.level
      }
    }
    if (column.children) {
      let colSpan = 0
      column.children.forEach((subColumn) => {
        traverse(subColumn, column)
        colSpan += subColumn.colSpan
      })
      column.colSpan = colSpan
    } else {
      column.colSpan = 1
    }
  }

  originColumns.forEach((column) => {
    column.level = 1
    traverse(column)
  })

  const rows = []
  for (let i = 0; i < maxLevel; i++) {
    rows.push([])
  }

  // 获取所有栏目数
  let allColumns = getAllColumns(originColumns);
  if (fixed === 'left') {
    allColumns = allColumns.filter(column => column.fixed === true || column.fixed === 'left')
  } else if (fixed === 'right') {
    allColumns = allColumns.filter(column => column.fixed === 'right')
  }

  allColumns.forEach((column) => {
    if (!column.children) {
      column.rowSpan = maxLevel - column.level + 1
    } else {
      column.rowSpan = 1
    }
    rows[column.level - 1].push(column)
  })
  //  返回所有行数
  return rows
}

// module
export default {
  name: config.prefix + '-table-header',
  mixins: [LayoutObserver],
  components: {
    checkbox,
    tag
  },
  render (h) {
    const originColumns = this.store.states.originColumns
    const hasFilter = originColumns.some(current => {
      return current.$slots.filter || current.filterType !== ''
    })

    // 栏目的行数
    const columnRows = convertToRows(originColumns, this.fixed)
    // 是否拥有多级表头
    const isGroup = columnRows.length > 1
    if (isGroup) {
      // 说明拥有多级表头
      this.$parent.isGroup = true
    }
    var _defaultSlot = this.$slots.default

    // 渲染的html
    return (
      <table class="aty-table__header" cellspacing="0" cellpadding="0" border="0">
        <colgroup>
          {
            this._l(this.columns.filter(column => column.isRender), column => <col name={column.id}/>)
          }
          {
            this.hasGutter ? <col name="gutter"/> : ''
          }
        </colgroup>
        <thead class={[{ 'is-group': isGroup, 'has-gutter': this.hasGutter }]}>
          {
            this._l(columnRows, (columns, rowIndex) =>
              <tr class={this.getHeaderRowClass(rowIndex)}>
                {
                  this._l(columns, (column, cellIndex) => {
                    if (!column.isRender) {
                      return ''
                    }
                    let filterContent = ''

                    if (column.$slots.filter) {
                      filterContent = column.$slots.filter
                    } else if (column.filterType !== '') {
                      filterContent = this.getFilterContent(h, column)
                    } else if (hasFilter) {
                      filterContent = '\u00A0'
                    }
                    let filterContetTop = ''
                    if (column.filterType !== '' || column.$slots.filter) {
                      if (column.filterTriggerOnSide) {
                        filterContent = filterContent ?
                                            <AtyDropDown transfer dropDownClassName={column.filterPopupClass}>
                                              <span slot="trigger" class="aty-table__column-filter-trigger" on-click={($event) => this.handleHeaderFilterClick($event)}>
                                                <i class={['aty-icon', 'aty-icon-funnel', this.filterOpened ? 'aty-icon-chevron-up' : '']}></i>
                                              </span>
                                              <AtyDropDownPanel style="padding: 20px 20px 20px 0; text-align: center;margin-left:20px" >
                                                {filterContent}
                                              </AtyDropDownPanel>
                                            </AtyDropDown> : ''
                      } else {
                        filterContetTop = <div class="filter-wrap">{filterContent}</div>
                      }
                    }

                    // cell不是object的情况才显示title
                    let title = column.renderHeader
                      ? column.renderHeader.call(this._renderProxy, h, {
                        column,
                        $index: cellIndex,
                        store: this.store,
                        _self: this.$parent.$vnode.context
                      })
                      : column.label
                    if (Artery.isOneOf(Artery.type(title), ['object', 'array'])) {
                      title = ''
                    }

                    let paddingRight = 0
                    if (column.sortable) {
                      paddingRight += 24
                    }
                    if (column.filterTriggerOnSide) {
                      paddingRight += 17
                    }
                    return <th colspan={column.colSpan}
                      rowspan={column.rowSpan}
                      on-mousemove={($event) => this.handleMouseMove($event, column)}
                      on-mouseout={this.handleMouseOut}
                      on-mousedown={($event) => this.handleMouseDown($event, column)}
                      on-contextmenu={($event) => this.handleHeaderContextMenu($event, column)}
                      class={this.getHeaderCellClass(rowIndex, cellIndex, columns, column)}>
                      {filterContetTop}
                      <div on-click={($event) => this.handleHeaderClick($event, column)}
                        class={['cell', column.labelClassName, column.showFilterTip ? 'filter-tip' : '']}
                        style={paddingRight ? { 'padding-right': paddingRight + 'px' } : ''}>
                        {
                          column.renderHeader
                            ? column.renderHeader.call(this._renderProxy, h, {
                              column,
                              $index: cellIndex,
                              store: this.store,
                              _self: this.$parent.$vnode.context
                            })
                            : <span title={title} class="title-wrapper">{column.label}</span>
                        }
                        {
                          column.sortable
                            ? <span class="caret-wrapper"
                              on-click={($event) => this.handleSortClick($event, column)}>
                              <i class="sort-caret ascending"
                                on-click={($event) => this.handleSortClick($event, column, 'ascending')}></i>
                              <i class="sort-caret descending"
                                on-click={($event) => this.handleSortClick($event, column, 'descending')}></i>
                            </span>
                            : <template></template>
                        }
                        {
                          column.filterTriggerOnSide
                            ? filterContent
                            : ''
                        }

                      </div>
                    </th>
                  }
                  )
                }
                {
                  this.hasGutter ? <th class="gutter"></th> : ''
                }
              </tr>
            )
          }
        </thead>
      </table>
    )
  },

  props: {
    fixed: String,
    store: {
      required: true
    },
    border: Boolean
  },
  data () {
    return {
      draggingColumn: null,
      dragging: false,
      dragState: {},
      filterData: {}
    }
  },
  computed: {
    table () {
      return this.$parent
    },

    isAllSelected () {
      return this.store.states.isAllSelected
    },

    columns () {
      if (this.fixed === 'left') {
        return this.store.states.fixedColumns
      } else if (this.fixed === 'right') {
        return this.store.states.rightFixedColumns
      }
      return this.store.states.columns
    },

    hasGutter () {
      return !this.fixed && this.tableLayout.gutterWidth
    }
  },

  methods: {
    /** 点击增加属性 filter-trigger-on-side 的过滤图标 */
    handleHeaderFilterClick () {
      // 这里拿出来是为了做异步加载
      this.$emit('tableFilterOpen')
      this.filterOpened = !this.filterOpened
    },

    getHeaderRowClass (rowIndex) {
      const classes = []

      if (this.fixed === 'left') {
        classes.push('aty-table__row--left-fixed');
      } else if (this.fixed === 'right') {
        classes.push('aty-table__row--right-fixed');
      } else {
        classes.push('aty-table__row--center');
      }

      const headerRowClassName = this.table.headerRowClassName
      if (typeof headerRowClassName === 'string') {
        classes.push(headerRowClassName)
      } else if (typeof headerRowClassName === 'function') {
        classes.push(headerRowClassName.call(null, { rowIndex }))
      }

      return classes.join(' ')
    },

    getHeaderCellClass (rowIndex, columnIndex, row, column) {
      const classes = [column.id, column.order, column.headerAlign, column.className, column.labelClassName]

      if (!column.children) {
        classes.push('is-leaf')
      }

      if (column.sortable) {
        classes.push('is-sortable')
      }

      const headerCellClassName = this.table.headerCellClassName
      if (typeof headerCellClassName === 'string') {
        classes.push(headerCellClassName)
      } else if (typeof headerCellClassName === 'function') {
        classes.push(headerCellClassName.call(null, {
          rowIndex,
          columnIndex,
          row,
          column
        }))
      }

      return classes.filter(c => c).join(' ')
    },
    toggleAllSelection () {
      this.store.commit('toggleAllSelection')
    },

    handleHeaderClick (event, column) {
      if (column.sortable) {
        this.handleSortClick(event, column)
      }
      /**
       * #event
       *
       * @name    header-click
       * @param   column 列数据
       * @param   event 事件
       * @body
       * @description 当某一列的表头被点击时会触发该事件。
       */
      this.$parent.$emit('header-click', column, event)
    },

    handleHeaderContextMenu (event, column) {
      /**
       * #event
       *
       * @name    header-contextmenu
       * @param   column 列数据
       * @param   event 事件
       * @body
       * @description 当某一列的表头被鼠标右键点击时触发该事件。
       */
      this.$parent.$emit('header-contextmenu', column, event)
    },

    handleMouseDown (event, column) {
      if (this.$isServer) return
      if (column.children && column.children.length > 0) return
      /* istanbul ignore if */
      if (this.draggingColumn && this.border) {
        this.dragging = true

        this.$parent.resizeProxyVisible = true

        const table = this.$parent
        const tableEl = table.$el
        const tableLeft = tableEl.getBoundingClientRect().left
        const columnEl = this.$el.querySelector(`th.${column.id}`)
        const columnRect = columnEl.getBoundingClientRect()
        const minLeft = columnRect.left - tableLeft + 30

        Artery.addClass(columnEl, 'noclick')

        this.dragState = {
          startMouseLeft: event.clientX,
          startLeft: columnRect.right - tableLeft,
          startColumnLeft: columnRect.left - tableLeft,
          tableLeft
        }

        const resizeProxy = table.$refs.resizeProxy
        resizeProxy.style.left = this.dragState.startLeft + 'px'

        document.onselectstart = function () {
          return false
        }
        document.ondragstart = function () {
          return false
        }

        const handleMouseMove = (event) => {
          const deltaLeft = event.clientX - this.dragState.startMouseLeft
          const proxyLeft = this.dragState.startLeft + deltaLeft

          resizeProxy.style.left = Math.max(minLeft, proxyLeft) + 'px'
        }

        const handleMouseUp = () => {
          if (this.dragging) {
            const {
              startColumnLeft,
              startLeft
            } = this.dragState
            const finalLeft = parseInt(resizeProxy.style.left, 10)
            const columnWidth = finalLeft - startColumnLeft
            column.width = column.realWidth = columnWidth
            /**
             * #event
             *
             * @name    header-dragend
             * @param   width 当前列宽
             * @param   oldWidth 原列宽
             * @param   column 列数据
             * @param   event 事件
             * @body
             * @description 当拖动表头改变了列的宽度的时候会触发该事件。
             */
            table.$emit('header-dragend', column.width, startLeft - startColumnLeft, column, event)

            this.store.scheduleLayout()

            document.body.style.cursor = ''
            this.dragging = false
            this.draggingColumn = null
            this.dragState = {}

            table.resizeProxyVisible = false
          }

          document.removeEventListener('mousemove', handleMouseMove)
          document.removeEventListener('mouseup', handleMouseUp)
          document.onselectstart = null
          document.ondragstart = null

          setTimeout(function () {
            Artery.removeClass(columnEl, 'noclick')
          }, 0)
        }

        document.addEventListener('mousemove', handleMouseMove)
        document.addEventListener('mouseup', handleMouseUp)
      }
    },

    handleMouseMove (event, column) {
      if (column.children && column.children.length > 0) return
      let target = event.target
      while (target && target.tagName !== 'TH') {
        target = target.parentNode
      }

      if (!column || !column.resizable) return

      if (!this.dragging && this.border) {
        const rect = target.getBoundingClientRect()

        const bodyStyle = document.body.style
        if (rect.width > 12 && rect.right - event.pageX < 8) {
          bodyStyle.cursor = 'col-resize'
          if (Artery.hasClass(target, 'is-sortable')) {
            target.style.cursor = 'col-resize'
          }
          this.draggingColumn = column
        } else if (!this.dragging) {
          bodyStyle.cursor = ''
          if (Artery.hasClass(target, 'is-sortable')) {
            target.style.cursor = 'pointer'
          }
          this.draggingColumn = null
        }
      }
    },

    handleMouseOut () {
      if (this.$isServer) return
      document.body.style.cursor = ''
    },

    toggleOrder (order) {
      return !order ? 'ascending' : order === 'ascending' ? 'descending' : null
    },

    /**
     * @param  event
     * @param  column
     * @param  givenOrder  {String}    ascending 升序，  descending 降序
     */
    handleSortClick (event, column, givenOrder) {
      event.stopPropagation()

      const order = givenOrder || this.toggleOrder(column.order)

      let target = event.target
      while (target && target.tagName !== 'TH') {
        target = target.parentNode
      }

      if (target && target.tagName === 'TH') {
        if (Artery.hasClass(target, 'noclick')) {
          Artery.removeClass(target, 'noclick')
          return
        }
      }

      if (!column.sortable) return

      const states = this.store.states
      let sortProp = states.sortProp
      let sortOrder
      const sortingColumn = states.sortingColumn

      if (sortingColumn !== column || (sortingColumn === column && sortingColumn.order === null)) {
        if (sortingColumn) {
          sortingColumn.order = null
        }
        states.sortingColumn = column
        sortProp = column.property
      }

      // 如果不排序
      if (!order) {
        sortOrder = column.order = null
        states.sortingColumn = null
        sortProp = null
      } else {
        sortOrder = column.order = order
      }

      states.sortProp = sortProp
      states.sortOrder = sortOrder

      this.store.commit('changeSortCondition')
    },
    handleFilterChange (column) {
      if (column) {
        column.showFilterTip = !isEmpty(column.filterValue)
        this.store.commit('filterChange_')
      }
    },
    getFilterContent (h, column) {
      if (column.filterType === '') {
        return ''
      }
      if (column.filterType === 'string') {
        return <aty-input clearable doValidate={false} v-model={column.filterValue}
          on-clear={() => {
            this.handleFilterChange(column)
          }
          }

          on-keydown={() => {
            if (event.keyCode === 13) {
              this.handleFilterChange(column)
            }
          }}></aty-input>
      }
      if (column.filterType === 'number' || column.filterType === 'int' || column.filterType === 'short') {
        if (column.filterValue === '') {
          column.filterValue = null
        }
        return <aty-input-number clearable doValidate={false} style="width:100%;" max={column.filterMax}
          min={column.filterMin} step={column.filterStep}
          v-model={column.filterValue}
          on-clear={() => {
            this.handleFilterChange(column)
          }
          }
          on-keydown={() => {
            if (event.keyCode === 13) {
              this.handleFilterChange(column)
            }
          }}></aty-input-number>
      }
      if (column.filterType === 'daterange') {
        return <aty-date-picker type="daterange" style="width:100%;" transfer split-panels
          v-model={column.filterValue} on-change={() => {
            this.handleFilterChange(column)
          }}></aty-date-picker>
      }
      if (column.filterType === 'code') {
        if (column.filterValue === '') {
          column.filterValue = column.filterMultiple ? [] : ''
        }
        return <aty-select clearable code-type={column.codeType} transfer multiple={column.filterMultiple} dropdownWidth={0}
          lazy={column.filterLazy} v-model={column.filterValue} on-change={() => {
            this.handleFilterChange(column)
          }}></aty-select>
      }
      let organType
      if (column.filterType === 'user') {
        organType = 'user'
      } else if (column.filterType === 'dept') {
        organType = 'dept'
      } else if (column.filterType === 'corp') {
        organType = 'corp'
      } else if (column.filterType === 'organ_all') {
        organType = 'all'
      }
      if (organType) {
        if (column.filterValue === '') {
          column.filterValue = column.filterMultiple ? [] : ''
        }
        return <aty-organ-tree clearable selectType={organType} selectScope={column.filterOrganScope} transfer dropdownWidth={0}
          multiple={column.filterMultiple} searchShowLimit={column.filterSearchShowLimit} v-model={column.filterValue} on-change={(newValue) => {
            this.handleFilterChange(column)
          }}></aty-organ-tree>
      }
    }
  },

  mounted () {
    this.$on('column-filter', (customfilter) => {
      this.store.states.originColumns.forEach(column => {
        const filterSlots = column.$slots.filter
        if (filterSlots) {
          const filterSlot = filterSlots[0]
          if (filterSlot && filterSlot.componentInstance && filterSlot.componentInstance === customfilter) {
            column.filterType = 'custom'
            column.filterValue = customfilter.currentFilterValue
            column.dataType = customfilter.dataType
            column.compareType = customfilter.compareType
            this.handleFilterChange(column)
          }
        }
      })
    })
  }

}
